home *** CD-ROM | disk | FTP | other *** search
/ Clickx 96 / Clickx 96.iso / software / tools / tool / xbmc-10.1.exe / addons / script.module.pil / lib / PIL / PsdImagePlugin.py < prev    next >
Encoding:
Python Source  |  2009-04-06  |  7.1 KB  |  292 lines

  1. #
  2. # The Python Imaging Library
  3. # $Id$
  4. #
  5. # Adobe PSD 2.5/3.0 file handling
  6. #
  7. # History:
  8. # 1995-09-01 fl   Created
  9. # 1997-01-03 fl   Read most PSD images
  10. # 1997-01-18 fl   Fixed P and CMYK support
  11. # 2001-10-21 fl   Added seek/tell support (for layers)
  12. #
  13. # Copyright (c) 1997-2001 by Secret Labs AB.
  14. # Copyright (c) 1995-2001 by Fredrik Lundh
  15. #
  16. # See the README file for information on usage and redistribution.
  17. #
  18.  
  19. __version__ = "0.4"
  20.  
  21. import Image, ImageFile, ImagePalette
  22.  
  23. MODES = {
  24.     # (photoshop mode, bits) -> (pil mode, required channels)
  25.     (0, 1): ("1", 1),
  26.     (0, 8): ("L", 1),
  27.     (1, 8): ("L", 1),
  28.     (2, 8): ("P", 1),
  29.     (3, 8): ("RGB", 3),
  30.     (4, 8): ("CMYK", 4),
  31.     (7, 8): ("L", 1), # FIXME: multilayer
  32.     (8, 8): ("L", 1), # duotone
  33.     (9, 8): ("LAB", 3)
  34. }
  35.  
  36. #
  37. # helpers
  38.  
  39. def i16(c):
  40.     return ord(c[1]) + (ord(c[0])<<8)
  41.  
  42. def i32(c):
  43.     return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
  44.  
  45. # --------------------------------------------------------------------.
  46. # read PSD images
  47.  
  48. def _accept(prefix):
  49.     return prefix[:4] == "8BPS"
  50.  
  51. ##
  52. # Image plugin for Photoshop images.
  53.  
  54. class PsdImageFile(ImageFile.ImageFile):
  55.  
  56.     format = "PSD"
  57.     format_description = "Adobe Photoshop"
  58.  
  59.     def _open(self):
  60.  
  61.         read = self.fp.read
  62.  
  63.         #
  64.         # header
  65.  
  66.         s = read(26)
  67.         if s[:4] != "8BPS" or i16(s[4:]) != 1:
  68.             raise SyntaxError, "not a PSD file"
  69.  
  70.         psd_bits = i16(s[22:])
  71.         psd_channels = i16(s[12:])
  72.         psd_mode = i16(s[24:])
  73.  
  74.         mode, channels = MODES[(psd_mode, psd_bits)]
  75.  
  76.         if channels > psd_channels:
  77.             raise IOError, "not enough channels"
  78.  
  79.         self.mode = mode
  80.         self.size = i32(s[18:]), i32(s[14:])
  81.  
  82.         #
  83.         # color mode data
  84.  
  85.         size = i32(read(4))
  86.         if size:
  87.             data = read(size)
  88.             if mode == "P" and size == 768:
  89.                 self.palette = ImagePalette.raw("RGB;L", data)
  90.  
  91.         #
  92.         # image resources
  93.  
  94.         self.resources = []
  95.  
  96.         size = i32(read(4))
  97.         if size:
  98.             # load resources
  99.             end = self.fp.tell() + size
  100.             while self.fp.tell() < end:
  101.                 signature = read(4)
  102.                 id = i16(read(2))
  103.                 name = read(ord(read(1)))
  104.                 if not (len(name) & 1):
  105.                     read(1) # padding
  106.                 data = read(i32(read(4)))
  107.                 if (len(data) & 1):
  108.                     read(1) # padding
  109.                 self.resources.append((id, name, data))
  110.                 if id == 1039: # ICC profile
  111.                     self.info["icc_profile"] = data
  112.  
  113.         #
  114.         # layer and mask information
  115.  
  116.         self.layers = []
  117.  
  118.         size = i32(read(4))
  119.         if size:
  120.             end = self.fp.tell() + size
  121.             size = i32(read(4))
  122.             if size:
  123.                 self.layers = _layerinfo(self.fp)
  124.             self.fp.seek(end)
  125.  
  126.         #
  127.         # image descriptor
  128.  
  129.         self.tile = _maketile(self.fp, mode, (0, 0) + self.size, channels)
  130.  
  131.         # keep the file open
  132.         self._fp = self.fp
  133.         self.frame = 0
  134.  
  135.     def seek(self, layer):
  136.         # seek to given layer (1..max)
  137.         if layer == self.frame:
  138.             return
  139.         try:
  140.             if layer <= 0:
  141.                 raise IndexError
  142.             name, mode, bbox, tile = self.layers[layer-1]
  143.             self.mode = mode
  144.             self.tile = tile
  145.             self.frame = layer
  146.             self.fp = self._fp
  147.             return name, bbox
  148.         except IndexError:
  149.             raise EOFError, "no such layer"
  150.  
  151.     def tell(self):
  152.         # return layer number (0=image, 1..max=layers)
  153.         return self.frame
  154.  
  155.     def load_prepare(self):
  156.         # create image memory if necessary
  157.         if not self.im or\
  158.            self.im.mode != self.mode or self.im.size != self.size:
  159.             self.im = Image.core.fill(self.mode, self.size, 0)
  160.         # create palette (optional)
  161.         if self.mode == "P":
  162.             Image.Image.load(self)
  163.  
  164. def _layerinfo(file):
  165.     # read layerinfo block
  166.     layers = []
  167.     read = file.read
  168.  
  169.     for i in range(abs(i16(read(2)))):
  170.  
  171.         # bounding box
  172.         y0 = i32(read(4)); x0 = i32(read(4))
  173.         y1 = i32(read(4)); x1 = i32(read(4))
  174.  
  175.         # image info
  176.         info = []
  177.         mode = []
  178.         for i in range(i16(read(2))):
  179.             type = i16(read(2))
  180.             if type == 65535:
  181.                 m = "A"
  182.             else:
  183.                 m = "RGB"[type]
  184.             mode.append(m)
  185.             size = i32(read(4))
  186.             info.append((m, size))
  187.  
  188.         # figure out the image mode
  189.         mode.sort()
  190.         if mode == ["R"]:
  191.             mode = "L"
  192.         elif mode == ["B", "G", "R"]:
  193.             mode = "RGB"
  194.         elif mode == ["A", "B", "G", "R"]:
  195.             mode = "RGBA"
  196.         else:
  197.             mode = None # unknown
  198.  
  199.         # skip over blend flags and extra information
  200.         filler = read(12)
  201.         name = ""
  202.         size = i32(read(4))
  203.         combined = 0
  204.         if size:
  205.             length = i32(read(4))
  206.             if length:
  207.                 mask_y = i32(read(4)); mask_x = i32(read(4))
  208.                 mask_h = i32(read(4)) - mask_y; mask_w = i32(read(4)) - mask_x
  209.                 file.seek(length - 16, 1)
  210.             combined += length + 4
  211.  
  212.             length = i32(read(4))
  213.             if length:
  214.                 file.seek(length, 1)
  215.             combined += length + 4
  216.  
  217.             length = ord(read(1))
  218.             if length:
  219.                 name = read(length)
  220.             combined += length + 1
  221.  
  222.         file.seek(size - combined, 1)
  223.         layers.append((name, mode, (x0, y0, x1, y1)))
  224.  
  225.     # get tiles
  226.     i = 0
  227.     for name, mode, bbox in layers:
  228.         tile = []
  229.         for m in mode:
  230.             t = _maketile(file, m, bbox, 1)
  231.             if t:
  232.                 tile.extend(t)
  233.         layers[i] = name, mode, bbox, tile
  234.         i = i + 1
  235.  
  236.     return layers
  237.  
  238. def _maketile(file, mode, bbox, channels):
  239.  
  240.     tile = None
  241.     read = file.read
  242.  
  243.     compression = i16(read(2))
  244.  
  245.     xsize = bbox[2] - bbox[0]
  246.     ysize = bbox[3] - bbox[1]
  247.  
  248.     offset = file.tell()
  249.  
  250.     if compression == 0:
  251.         #
  252.         # raw compression
  253.         tile = []
  254.         for channel in range(channels):
  255.             layer = mode[channel]
  256.             if mode == "CMYK":
  257.                 layer = layer + ";I"
  258.             tile.append(("raw", bbox, offset, layer))
  259.             offset = offset + xsize*ysize
  260.  
  261.     elif compression == 1:
  262.         #
  263.         # packbits compression
  264.         i = 0
  265.         tile = []
  266.         bytecount = read(channels * ysize * 2)
  267.         offset = file.tell()
  268.         for channel in range(channels):
  269.             layer = mode[channel]
  270.             if mode == "CMYK":
  271.                 layer = layer + ";I"
  272.             tile.append(
  273.                 ("packbits", bbox, offset, layer)
  274.                 )
  275.             for y in range(ysize):
  276.                 offset = offset + i16(bytecount[i:i+2])
  277.                 i = i + 2
  278.  
  279.     file.seek(offset)
  280.  
  281.     if offset & 1:
  282.         read(1) # padding
  283.  
  284.     return tile
  285.  
  286. # --------------------------------------------------------------------
  287. # registry
  288.  
  289. Image.register_open("PSD", PsdImageFile, _accept)
  290.  
  291. Image.register_extension("PSD", ".psd")
  292.